/**
 * Stores accumulated bit counts.
 * 
 * @author Yong Shin
 *
 */
public class BitCounts implements Comparable<BitCounts> {
	
	public int zeroBits;
	public int oneBits;
	
	public BitCounts(int zeroBits, int oneBits) {
		this.zeroBits = zeroBits;
		this.oneBits = oneBits;
	}
        
        public BitCounts(BitCounts b){
                this.zeroBits = b.zeroBits;
                this.oneBits = b.oneBits;
        }

    public double getEntropy() {
	return Cost.firstOrderEntropy(this);
    }

    public double getAdaptiveCost() {
	return Cost.adaptiveCostEstimate(this);
    }
	
	public void add(BitCounts bcounts) {
		zeroBits += bcounts.zeroBits;
		oneBits += bcounts.oneBits;
	}

	public void subtract(BitCounts bcounts) {
		zeroBits -= bcounts.zeroBits;
		oneBits -= bcounts.oneBits;
	}

	// natural ordering is first by ratio of zeroBits/oneBits where
	//   (0,0) is smallest
	//  use # totalbits as tiebreaker ( so (1,2) < (2,4))
	public int compareTo(BitCounts other) {
	    long compareval =  (long) this.zeroBits * (long) other.oneBits -
		(long) this.oneBits * (long)other.zeroBits;
	    if (compareval !=0) {
		if (compareval >0) return 1;
		else return -1;
	    }
	    else return 
		     this.zeroBits + this.oneBits - 
		     other.zeroBits - other.oneBits;
	}
	
	// does the ratio zeroBits/oneBits equal each other?
	// (0,0) is not equal to any other BitCounts object
	public boolean ratioEquals(BitCounts other) {
	    if (this.zeroBits + this.oneBits ==0 )
		return (other.zeroBits + other.oneBits ==0);
	    else if (other.zeroBits + other.oneBits ==0) {
		// this != (0,0) && other == (0,0), 
		return false;
	    }
	    else {
		// both not (0,0)
		long compareval =  (long) this.zeroBits * (long) other.oneBits
		    - (long) this.oneBits * (long)other.zeroBits;
		return compareval == 0;
	    }
	}

	@Override
	    public boolean equals(Object other) {
	    if (other instanceof BitCounts) {
		BitCounts o = (BitCounts) other;
		return (this.zeroBits == o.zeroBits) &&
		    this.oneBits == o.oneBits;
	    }
	    else return false;
	}
	
	@Override
	public String toString() {
		return zeroBits + " " + oneBits;
	}
}
